package com.anandsoftware.service.impl;

import java.util.Map;
import java.util.Map.Entry;

import com.anandsoftware.application.ApplicationContext;
import com.anandsoftware.db.io.DatabaseIO;
import com.anandsoftware.security.SecurityAlgorithm;
import com.anandsoftware.security.SecurityUtil;
import com.anandsoftware.security.impl.BlowFish;
import com.anandsoftware.service.AuthenticateService;
import com.anandsoftware.system.domain.SystemInformation;
import com.google.gson.Gson;

public class AuthenticateServiceImpl extends BaseServiceImpl implements
		AuthenticateService {

	/**
	 * @param systemInformation
	 *            receives Systeminformation
	 * @param key
	 *            key received from server
	 * @param myID
	 *            id of a software
	 * @return returns true if Authenticated else false.
	 */
	@Override
	public boolean authenticateOnline(SystemInformation systemInformation,
			String key, String myID) {
		// TODO Auto-generated method stub

		String jsonSystemInformation = new Gson().toJson(systemInformation);
		BlowFish blowFish = SecurityUtil
				.getInstance(SecurityAlgorithm.BLOWFISH);
		blowFish.setKey(key);
		blowFish.setIv(ApplicationContext.DEFAULT_IV);
		String encryptedJson = blowFish.encrypt(jsonSystemInformation);
		String responce = sendPostRequest(
				ApplicationContext.AUTHENTICATE_SERVICE_TOKEN + encryptedJson
						+ "&" + ApplicationContext.REQUEST_ACCESS_TOKEN + myID,
				AUTHENTICATE_SERVICE_REQUEST_URL);

		try {
			int auth = Integer.parseInt(responce.trim());
			if (auth > 2) {
				return true;
			}
		} catch (NumberFormatException e) {
			System.out.println("ERROR: can not parse : " + responce);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	/**
	 * @param systemInformation
	 *            recives SystemInformation
	 * @return returns true if Authenticated else false.
	 */
	@Override
	public boolean authenticateOffline(SystemInformation systemInformation,
			DatabaseIO dbIO) {
		// TODO Auto-generated method stub
		SystemInformation sysInfo = new SystemInformation();
		int authPoints = 0;
		sysInfo.setMacIdList(systemInformation.getMacIdList());
		sysInfo.setOsDriveSerialNumber(systemInformation
				.getOsDriveSerialNumber());
		sysInfo.setOsProductKey(systemInformation.getOsProductKey());
		Map<String, String> map = SecurityUtil.encryptPropertyAndValue(sysInfo,
				SecurityAlgorithm.SHA1);

		for (Entry<String, String> entry : map.entrySet()) {
			String value = dbIO.getValue(entry.getKey());
			if (value.trim().equalsIgnoreCase(entry.getValue().trim())) {
				authPoints++;
			}
		}
		System.out.println("INFO: Auth Points: " + authPoints);
		if (authPoints > 2) {
			return true;
		}
		return false;
	}

	@Override
	public boolean authenticateWeakOnline(SystemInformation systemInformation,
			String key, String myID) {

		String jsonSystemInformation = new Gson().toJson(systemInformation);
		BlowFish blowFish = SecurityUtil
				.getInstance(SecurityAlgorithm.BLOWFISH);
		blowFish.setKey(key);
		blowFish.setIv(ApplicationContext.DEFAULT_IV);
		String encryptedJson = blowFish.encrypt(jsonSystemInformation);
		String responce = sendPostRequest(
				ApplicationContext.AUTHENTICATE_SERVICE_TOKEN + encryptedJson
						+ "&" + ApplicationContext.REQUEST_ACCESS_TOKEN + myID,
				AUTHENTICATE_SERVICE_REQUEST_URL);

		try {
			int auth = Integer.parseInt(responce.trim());
			if (auth > 1) {
				return true;
			}
		} catch (NumberFormatException e) {
			System.out.println("ERROR: can not parse : " + responce);
		} catch (Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	@Override
	public boolean authenticateWeakOffline(SystemInformation systemInformation,
			DatabaseIO dbIO) {
		// TODO Auto-generated method stub
		SystemInformation sysInfo = new SystemInformation();
		int authPoints = 0;
		sysInfo.setMacIdList(systemInformation.getMacIdList());
		sysInfo.setOsDriveSerialNumber(systemInformation
				.getOsDriveSerialNumber());
		sysInfo.setOsProductKey(systemInformation.getOsProductKey());
		Map<String, String> map = SecurityUtil.encryptPropertyAndValue(sysInfo,
				SecurityAlgorithm.SHA1);

		for (Entry<String, String> entry : map.entrySet()) {
			String value = dbIO.getValue(entry.getKey());
			if (value.trim().equalsIgnoreCase(entry.getValue().trim())) {
				authPoints++;
			}
		}

		System.out.println("INFO: Auth Points:" + authPoints);
		if (authPoints > 1) {
			return true;
		}
		return false;
	}

}
